/**
 * Copyright (C) 2021-2022 maminjie <canpool@163.com>
 * SPDX-License-Identifier: LGPL-2.1
 * Powered by Qt-Advanced-Docking-System
**/
/**
 * Copyright (C) 2021-2022 maminjie <canpool@163.com>
 * SPDX-License-Identifier: LGPL-2.1
 * Powered by Qt-Advanced-Docking-System
**/

#pragma once

#include <QtCore/QtGlobal>

class QWidget;

#ifndef QADS_STATIC
#ifdef QADS_LIBRARY
#define QADS_EXPORT Q_DECL_EXPORT
#else
#define QADS_EXPORT Q_DECL_IMPORT
#endif
#else
#define QADS_EXPORT
#endif

#if !defined(QADS_NAMESPACE_DISABLE)
#define QADS_NAMESPACE  QAds
#endif

#if !defined(QADS_NAMESPACE)
#define QADS_BEGIN_NAMESPACE
#define QADS_END_NAMESPACE
#define QADS_USE_NAMESPACE
#define QADS_PREPEND_NAMESPACE(name) name
#else
#define QADS_BEGIN_NAMESPACE namespace QADS_NAMESPACE {
#define QADS_END_NAMESPACE }
#define QADS_USE_NAMESPACE using namespace QADS_NAMESPACE;
#define QADS_PREPEND_NAMESPACE(name) QADS_NAMESPACE::name
#endif // QADS_NAMESPACE

QADS_BEGIN_NAMESPACE
// nothing
QADS_END_NAMESPACE

// Define QADS_DEBUG_PRINT to enable a lot of debug output
#ifdef QADS_DEBUG_PRINT
#define QADS_PRINT(s) qDebug() << s
#else
#define QADS_PRINT(s)
#endif

// Set QADS_DEBUG_LEVEL to enable additional debug output and to enable layout
// dumps to qDebug and std::cout after layout changes
#define QADS_DEBUG_LEVEL 0

namespace QAds {

enum DockWidgetArea {
    NoDockWidgetArea = 0x00,
    LeftDockWidgetArea = 0x01,
    RightDockWidgetArea = 0x02,
    TopDockWidgetArea = 0x04,
    BottomDockWidgetArea = 0x08,
    CenterDockWidgetArea = 0x10,

    InvalidDockWidgetArea = NoDockWidgetArea,
    OuterDockAreas = TopDockWidgetArea | LeftDockWidgetArea | RightDockWidgetArea | BottomDockWidgetArea,
    AllDockAreas = OuterDockAreas | CenterDockWidgetArea
};
Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea)

enum TitleBarButtonRole {
    TabsMenuButton,
    UndockButton,
    CloseButton
};

/**
 * The different dragging states
 */
enum DragState {
    DraggingInactive,
    DraggingMousePressed,
    DraggingTab,
    DraggingFloatingWidget
};

/**
 * The different icons used in the UI
 */
enum IconRole {
    TabCloseIcon,
    TitleBarTabsMenuIcon,
    TitleBarUndockIcon,
    TitleBarCloseIcon,
    FloatingWidgetCloseIcon
};
const int ICON_ROLE_CNT = 5;

/**
 * For bitwise combination of dock wdget features
 */
enum BitwiseOperator {
    BitwiseAnd,
    BitwiseOr
};

/**
 * These global configuration flags configure some global dock settings.
 * Set the config flags, before you create the dock manager instance.
 */
enum ConfigFlag {
    ActiveTabHasCloseButton = 0x0001,   //!< If this flag is set, the active tab in a tab area has a close button
    TitleBarHasCloseButton = 0x0002,    //!< If the flag is set each dock pannel has a close button
    TitleBarCloseButtonClosesTab = 0x0004, //!< If the flag is set, the dock pannel close button closes the active tab, if not set, it closes the complete dock area
    OpaqueSplitterResize = 0x0008,      //!< See QSplitter::setOpaqueResize() documentation
    XmlAutoFormattingEnabled = 0x0010,  //!< If enabled, the XML writer automatically adds line-breaks and indentation to empty sections between elements (ignorable whitespace).
    XmlCompressionEnabled = 0x0020,     //!< If enabled, the XML output will be compressed and is not human readable anymore
    TabCloseButtonIsToolButton = 0x0040, //! If enabled the tab close buttons will be QToolButtons instead of QPushButtons - disabled by default
    AllTabsHaveCloseButton = 0x0080,    //!< if this flag is set, then all tabs that are closable show a close button
    RetainTabSizeWhenCloseButtonHidden = 0x0100, //!< if this flag is set, the space for the close button is reserved even if the close button is not visible
    OpaqueUndocking = 0x0200,           ///< If enabled, the widgets are immediately undocked into floating widgets, if disabled, only a draw preview is undocked and the real undocking is deferred until the mouse is released
    DragPreviewIsDynamic = 0x0400,      ///< If opaque undocking is disabled, this flag defines the behavior of the drag preview window, if this flag is enabled, the preview will be adjusted dynamically to the drop area
    DragPreviewShowsContentPixmap = 0x0800, ///< If opaque undocking is disabled, the created drag preview window shows a copy of the content of the dock widget / dock are that is dragged
    DragPreviewHasWindowFrame = 0x1000, ///< If opaque undocking is disabled, then this flag configures if the drag preview is frameless or looks like a real window
    AlwaysShowTabs = 0x2000,            ///< If this option is enabled, the tab of a dock widget is always displayed - even if it is the only visible dock widget in a floating widget.
    TitleBarHasUndockButton = 0x4000,   //!< If the flag is set each dock pannel has an undock button
    TitleBarHasTabsMenuButton = 0x8000, //!< If the flag is set each dock pannel has a tabs menu button
    TitleBarHideDisabledButtons = 0x10000, //!< If the flag is set disabled dock pannel buttons will not appear on the tollbar at all (enabling them will bring them back)
    TitleBarDynamicTabsMenuButtonVisibility = 0x20000, //!< If the flag is set, the tabs menu button will be shown only when it is required - that means, if the tabs are elided. If the tabs are not elided, it is hidden
    FloatingContainerHasWidgetTitle = 0x40000,  //!< If set, the Floating Widget window title reflects the title of the current dock widget otherwise it displays application name as window title
    FloatingContainerHasWidgetIcon = 0x80000,   //!< If set, the Floating Widget icon reflects the icon of the current dock widget otherwise it displays application icon
    HideSingleCentralWidgetTitleBar = 0x100000, //!< If there is only one single visible dock widget in the main dock container (the dock manager) and if this flag is set, then the titlebar of this dock widget will be hidden
                                                //!< this only makes sense for non draggable and non floatable widgets and enables the creation of some kind of "central" widget
    FocusHighlighting = 0x200000,       //!< enables styling of focused dock widget tabs or floating widget titlebar
    EqualSplitOnInsertion = 0x400000,   ///!< if enabled, the space is equally distributed to all widgets in a splitter

    FloatingContainerForceNativeTitleBar = 0x800000, //!< Linux only ! Forces all FloatingContainer to use the native title bar. This might break docking for FloatinContainer on some Window Managers (like Kwin/KDE).
                                                     //!< If neither this nor FloatingContainerForceCustomTitleBar is set (the default) native titlebars are used except on known bad systems.
                                                     //! Users can overwrite this by setting the environment variable ADS_UseNativeTitle to "1" or "0".
    FloatingContainerForceQWidgetTitleBar = 0x1000000,//!< Linux only ! Forces all FloatingContainer to use a QWidget based title bar.
                                                     //!< If neither this nor FloatingContainerForceNativeTitleBar is set (the default) native titlebars are used except on known bad systems.
    MiddleMouseButtonClosesTab = 0x2000000, //! If the flag is set, the user can use the mouse middle button to close the tab under the mouse

    DefaultTitleBarButtons = TitleBarHasCloseButton | TitleBarHasUndockButton | TitleBarHasTabsMenuButton,///< default configuration of dock area title bar buttons
    DefaultBaseConfig = DefaultTitleBarButtons | ActiveTabHasCloseButton | XmlCompressionEnabled | FloatingContainerHasWidgetTitle,///< default base configuration settings
    DefaultOpaqueConfig = DefaultBaseConfig | OpaqueSplitterResize | OpaqueUndocking, ///< the default configuration with opaque operations - this may cause issues if ActiveX or Qt 3D windows are involved
    DefaultNonOpaqueConfig = DefaultBaseConfig | DragPreviewShowsContentPixmap, ///< the default configuration for non opaque operations
    NonOpaqueWithWindowFrame = DefaultNonOpaqueConfig | DragPreviewHasWindowFrame ///< the default configuration for non opaque operations that show a real window with frame
};
Q_DECLARE_FLAGS(ConfigFlags, ConfigFlag)

QADS_EXPORT ConfigFlags configFlags();
QADS_EXPORT void setConfigFlags(const ConfigFlags flags);
QADS_EXPORT void setConfigFlag(ConfigFlag flag, bool on = true);
QADS_EXPORT bool testConfigFlag(ConfigFlag flag);

namespace internal
{
/**
 * Searches for the parent widget of the given type.
 * Returns the parent widget of the given widget or 0 if the widget is not
 * child of any widget of type T
 *
 * It is not safe to use this function in in DockWidget because only
 * the current dock widget has a parent. All dock widgets that are not the
 * current dock widget in a dock area have no parent.
 */
template<class T>
T findParent(const QWidget *widget)
{
    QWidget *parentWidget = widget->parentWidget();
    while (parentWidget) {
        T parentImpl = qobject_cast<T>(parentWidget);
        if (parentImpl) {
            return parentImpl;
        }
        parentWidget = parentWidget->parentWidget();
    }
    return 0;
}

} // namespace internal
} // namespace QAds

Q_DECLARE_OPERATORS_FOR_FLAGS(QAds::DockWidgetAreas)
Q_DECLARE_OPERATORS_FOR_FLAGS(QAds::ConfigFlags)
